package com.codefish.framework.spring.beans.factory.support;

import com.codefish.framework.spring.beans.factory.IDisposableBean;
import com.codefish.framework.spring.core.utils.ClassUtils;
import com.codefish.framework.spring.core.utils.StringUtils;
import lombok.Getter;

/**
 * 作为IDisposableBean的适配器类，能够获取到目标bean的自定义destroy方法，
 * 并且实现destroy()方法来添加执行自定义的销毁方法
 *
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/10/06 下午 09:17
 */
@Getter
public class DisposableBeanAdapter implements IDisposableBean {
    private static final String CLOSE_METHOD_NAME = "close";
    private static final String SHUTDOWN_METHOD_NAME = "shutdown";
    private final String beanName;
    private final Object bean;
    private String destroyMethodName;


    public DisposableBeanAdapter(String beanName, Object bean, BeanDefinition beanDefinition) {
        this.beanName = beanName;
        this.bean = bean;
        String expectedDestroyMethodName = determiningDestroyMethodName(bean, beanDefinition);
        if (expectedDestroyMethodName != null && !"destroy".equals(expectedDestroyMethodName)) {
            this.destroyMethodName = expectedDestroyMethodName;
        }
    }


    @Override
    public void destroy() throws Exception {
        //如果bean实现了IDisposableBean，则首先调用bean的destroy()方法
        if (bean instanceof IDisposableBean) {
            ((IDisposableBean) bean).destroy();
        }
        //如果自定义销毁方法不为null，执行bean的自定义销毁方法
        if (destroyMethodName != null) {
            ClassUtils.invokeMethod(bean, destroyMethodName, Void.class);
        }
    }

    protected String determiningDestroyMethodName(Object bean, BeanDefinition beanDefinition) {
        String destroyMethodName = beanDefinition.getDestroyMethod();
        if (destroyMethodName == null && bean instanceof AutoCloseable) {
            //对实现了AutoCloseable的类实实例销毁时调用close()或shutdown()方法
            try {
                return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
            } catch (NoSuchMethodException ex) {
                try {
                    return bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
                } catch (NoSuchMethodException e) {
                    // 没有合适的方法
                }
            }
        }
        return !StringUtils.isEmpty(destroyMethodName) ? destroyMethodName : null;
    }
}
